package io.netty.http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.SocketAddress;


/**
 * HTTP服务端处理器
 *
 * @author Verlet
 * @date 2023-02-01 01:06
 */
@Slf4j
public class NettyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        log.info("客户端地址：{}", ctx.channel().remoteAddress());
        log.info("msg 类型: {}", msg.getClass());
        if (msg instanceof HttpRequest httpRequest) {
            String uri = httpRequest.uri();
            log.info("URI: {}", uri);
            ByteBuf byteBuf = Unpooled.copiedBuffer("欢迎访问服务器。。。", CharsetUtil.UTF_8);
            // 构造一个HTTP 响应
            DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=utf-8");
            httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());
            ctx.channel().writeAndFlush(httpResponse);
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        if (evt instanceof IdleStateEvent idleStateEvent) {
            switch (idleStateEvent.state()) {
                case READER_IDLE -> log.info("{} 读空闲", socketAddress);
                case WRITER_IDLE -> log.info("{} 写空闲", socketAddress);
                case ALL_IDLE -> {
                    log.info("{} 读写空闲", socketAddress);
                    // 空闲关掉channel 也可以在channel设置ReadTimeoutHandler
                    ctx.channel().close();
                    log.info("{} 关掉channel成功",socketAddress);
                }
            }
        }
    }

}
